﻿using System.Text.RegularExpressions;
using NGourd.Core.Runners;

namespace NGourd.CLI
{
    class CommandLineParser
    {

        private readonly Configuration config;
        private readonly Options Options;

        private CommandLineParser(Configuration cfg, Options options)
        {
            config = cfg;
            Options = options;
        }

        public static IConfiguration Parse<TOptions>(string[] args) where TOptions : Options, new()
        {
            return new CommandLineParser(BuildDefaultConfig(), new TOptions()).ParseArgs(args);
        }

        private static Configuration BuildDefaultConfig()
        {
            var config = new Configuration();
            new SetupDefaultConfigurationTweak().ApplyTo(config);
            return config;
        }

        private IConfiguration ParseArgs(string[] args)
        {
            foreach (var arg in args)
                CreateConfigurationTweakFromArg(arg).ApplyTo(config);

            return config;
        }

        private IConfigurationTweak CreateConfigurationTweakFromArg(string arg)
        {
            var optionFinder = Regex.Match(arg, @"^--?([^=]*)(=(.*))?$");
            if (optionFinder.Success)
            {
                var option = optionFinder.Groups[1].Value;
                string value = GetOptionalValue(optionFinder);
                return Options.GetTweakForOption(option, value);
            }
            else
            {
                return GetFileConfigurationTweak(arg);
            }
        }

        private IConfigurationTweak GetFileConfigurationTweak(string arg)
        {
            if (arg.EndsWith(".feature", System.StringComparison.CurrentCultureIgnoreCase))
                return new AddFeatureFileToConfigurationTweak(arg);
            return new AddAssemblyConfigurationTweak(arg);
        }

        private static string GetOptionalValue(Match optionFinder)
        {
            string value = null;
            if (optionFinder.Groups.Count > 3)
                value = optionFinder.Groups[3].Value;
            return value;
        }
    }
}
